package com.mytijian.openapi.core.client;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mytijian.openapi.adapter.dingding.result.UserInfo;
import com.mytijian.openapi.core.client.param.BookParam;
import com.mytijian.openapi.core.client.param.ChangeExamDateParam;
import com.mytijian.openapi.core.client.param.RegisterParam;
import com.mytijian.openapi.core.client.result.BaseResult;
import com.mytijian.openapi.core.client.result.BookResult;
import com.mytijian.openapi.core.client.result.CounterResult;
import com.mytijian.openapi.core.client.result.HospitalListResult;
import com.mytijian.openapi.core.client.result.MealInfo;
import com.mytijian.openapi.core.client.result.MealListResult;
import com.mytijian.openapi.core.client.result.OrderListResult;
import com.mytijian.openapi.core.client.result.RegisterResult;
import com.mytijian.openapi.core.model.AppConfig;
import com.mytijian.openapi.core.utils.HttpUtils;
import com.mytijian.openapi.core.utils.MD5;

/**
 * <pre>
 * open-api 基础client 仅提供了基础的接口调用不
 * 
 * @author clozz
 *
 */
@Component
public class OpenAPIClient implements IOpenAPIClient {

	private static interface Apis {
		String accessToken = "/accesstoken";
		String nonce = "/nonce";
		String register = "/sso/user/registerUser";
		String updateUserInfo = "/sso/user/updateUserInfo";
		String listHospital = "/resource/listHospitalsOfChannel";
		String getMeals = "/resource/listMealsOfHospital";
		String counter = "/counter/queryOrderableCapacity";
		/**
		 * 时间太紧急 二期上线
		 */
		String pdfReport = "/examreport/queryExamReportPDF";
		String getOrder = "/order/queryOrderByOrderNums";
		String orderBook = "/order/book";
		String revokeOrder = "/order/revokeOrder";
		String getMealByTmallProductId = "/resource/getMealByGoodsId";
		String nonpNosign = "/nonp-nosign";
		String changeExamDate = "/order/changeExamDate";
		String userInfo = "/sso/user/userInfo";
	}

	/* (non-Javadoc)
	 * @see com.mytijian.openapi.core.client.IOpenAPIClinet#getAccessToken(com.mytijian.openapi.core.model.OpenConfig)
	 */
	@Override
	public String getAccessToken(AppConfig config) {
		String url = String.format("%s%s?appKey=%s&appSecret=%s", config.getBaseUrl(), Apis.accessToken, config.getAppKey(), config.getAppSecret());
		String string = HttpUtils.doGet(url);
		System.out.println(url);
		System.out.println(string);
		JSONObject json = JSON.parseObject(string);
		String token = json.getString("accessToken");
		return token;

	}

	/* (non-Javadoc)
	 * @see com.mytijian.openapi.core.client.IOpenAPIClinet#nonce(com.mytijian.openapi.core.model.OpenConfig)
	 */
	@Override
	public String nonce(AppConfig config) {
		String url = String.format("%s%s?accessToken=%s", config.getBaseUrl(), Apis.nonce, config.getAppAccessToken());
		String string = HttpUtils.doGet(url);
		JSONObject json = JSON.parseObject(string);
		String token = json.getString("result");
		return token;
	}
	
	
	@Override
	public String getPDFExamReport(AppConfig config, String orderNum) {
		String url = String.format("%s%s?accessToken=%s", config.getBaseUrl(), Apis.pdfReport, config.getAppAccessToken());
		String postJSON = "{'orderNum':'"+orderNum+"'}";
		String string = HttpUtils.doPostJSON(url, postJSON);
		JSONObject json = JSON.parseObject(string);
		String encodedBase64 = json.getString("result");
		return encodedBase64;
	}

	/* (non-Javadoc)
	 * @see com.mytijian.openapi.core.client.IOpenAPIClinet#register(com.mytijian.openapi.core.model.OpenConfig, com.mytijian.openapi.core.client.param.RegisterParam)
	 */
	@Override
	public RegisterResult register(AppConfig config, RegisterParam param) {

		String nonce = nonce(config);

		String postJSON = JSON.toJSONString(param);

		String sign = MD5.stringMD5(String.format("%s%s%s", nonce, postJSON, config.getAppSignKey()));

		String postUrl = String.format("%s%s?accessToken=%s&nonce=%s&sign=%s", config.getBaseUrl(), Apis.register, config.getAppAccessToken(),
				nonce, sign);

		String string = HttpUtils.doPostJSON(postUrl, postJSON);

		return parseToJavaObject(string,RegisterResult.class);
	}

	/* (non-Javadoc)
	 * @see com.mytijian.openapi.core.client.IOpenAPIClinet#updateUserInfo(com.mytijian.openapi.core.model.OpenConfig, com.mytijian.openapi.core.client.param.RegisterParam)
	 */
	@Override
	public RegisterResult updateUserInfo(AppConfig config, RegisterParam param) {

		String nonce = nonce(config);

		String postJSON = JSON.toJSONString(param);

		String sign = MD5.stringMD5(String.format("%s%s%s", nonce, postJSON, config.getAppSignKey()));

		String postUrl = String.format("%s%s?accessToken=%s&nonce=%s&sign=%s", config.getBaseUrl(), Apis.updateUserInfo,
				config.getAppAccessToken(), nonce, sign);

		String string = HttpUtils.doPostJSON(postUrl, postJSON);
		
		return parseToJavaObject(string, RegisterResult.class);
	}

	/* (non-Javadoc)
	 * @see com.mytijian.openapi.core.client.IOpenAPIClinet#listHospital(com.mytijian.openapi.core.model.OpenConfig)
	 */
	@Override
	public HospitalListResult listHospital(AppConfig config) {
		String url = String.format("%s%s?accessToken=%s", config.getBaseUrl(), Apis.listHospital, config.getAppAccessToken());

		String string = HttpUtils.doGet(url);

		return parseToJavaObject(string, HospitalListResult.class);
	}

	/* (non-Javadoc)
	 * @see com.mytijian.openapi.core.client.IOpenAPIClinet#getMeals(com.mytijian.openapi.core.model.OpenConfig, java.lang.Integer)
	 */
	@Override
	public MealListResult getMeals(AppConfig config, Integer mealId) {
		String url = String.format("%s%s?accessToken=%s", config.getBaseUrl(), Apis.getMeals, config.getAppAccessToken());

		String postJSON = "{mealIds:[" + mealId + "]}";

		String string = HttpUtils.doPostJSON(url, postJSON);

		return parseToJavaObject(string, MealListResult.class);
	}

	/* (non-Javadoc)
	 * @see com.mytijian.openapi.core.client.IOpenAPIClinet#getCounter(com.mytijian.openapi.core.model.OpenConfig, java.lang.Integer, java.lang.String, java.lang.String)
	 */
	@Override
	public CounterResult getCounter(AppConfig config, Integer hosptailId, String startDate,
			String endDate) {

		String url = String.format("%s%s?accessToken=%s", config.getBaseUrl(), Apis.counter, config.getAppAccessToken());
		Map<String, String> map = new HashMap<>();

		map.put("hospitalId", String.valueOf(hosptailId));
		map.put("startDate", startDate);
		map.put("endDate", endDate);

		String postJSON = JSON.toJSONString(map);

		String string = HttpUtils.doPostJSON(url, postJSON);

		return parseToJavaObject(string, CounterResult.class);
	}

	/* (non-Javadoc)
	 * @see com.mytijian.openapi.core.client.IOpenAPIClinet#book(com.mytijian.openapi.core.model.OpenConfig, com.mytijian.openapi.core.client.param.BookParam)
	 */
	@Override
	public BookResult book(AppConfig config, BookParam param) {
		String nonce = nonce(config);
		String postJSON = JSON.toJSONString(param);

		String sign = MD5.stringMD5(String.format("%s%s%s", nonce, postJSON, config.getAppSignKey()));

		String postUrl = String.format("%s%s?accessToken=%s&nonce=%s&sign=%s", config.getBaseUrl(), Apis.orderBook, config.getAppAccessToken(),
				nonce, sign);

		String string = HttpUtils.doPostJSON(postUrl, postJSON);
		
		return parseToJavaObject(string, BookResult.class);
	}
	

	/* (non-Javadoc)
	 * @see com.mytijian.openapi.core.client.IOpenAPIClinet#revoke(com.mytijian.openapi.core.model.OpenConfig, java.lang.String)
	 */
	@Override
	public BaseResult revoke(AppConfig config, String orderNum) {
		String nonce = nonce(config);

		String postJSON = "{\"orderNum\":\"" + orderNum + "\"}";
		String sign = MD5.stringMD5(String.format("%s%s%s", nonce, postJSON,config.getAppSignKey()));

		String postUrl = String.format("%s%s?accessToken=%s&nonce=%s&sign=%s", config.getBaseUrl(), Apis.revokeOrder, config.getAppAccessToken(),
				nonce, sign);

		String string = HttpUtils.doPostJSON(postUrl, postJSON);
		
		return parseToJavaObject(string, BaseResult.class);
	}

	public OrderListResult getOrderStatus(AppConfig config, String orderNum) {
		String url = String.format("%s%s?accessToken=%s", config.getBaseUrl(), Apis.getOrder, config.getAppAccessToken());

		String postJSON = "{orderNums:[\"" + orderNum + "\"]}";

		String string = HttpUtils.doPostJSON(url, postJSON);
		
		return parseToJavaObject(string, OrderListResult.class);
	}
	
	public OrderListResult getOrderStatus(AppConfig config, List<String> orderNums) {
		String url = String.format("%s%s?accessToken=%s", config.getBaseUrl(), Apis.getOrder, config.getAppAccessToken());

		StringBuffer sb = new StringBuffer();
		
		for (String orderNum : orderNums) {
			sb.append("\"").append(orderNum).append("\",");
		}
		sb = sb.deleteCharAt(sb.length()-1);
		String postJSON = "{orderNums:[" + sb.toString() + "]}";

		String string = HttpUtils.doPostJSON(url, postJSON);
		
		return parseToJavaObject(string, OrderListResult.class);
	}
	
	@Override
	public MealInfo getMealByTmallProductId(AppConfig config, String tmallProductId) {
		String url = String.format("%s%s?accessToken=%s", config.getBaseUrl(), Apis.getMealByTmallProductId, config.getAppAccessToken());
		
		String postJSON = "{\"goodsId\":\""+tmallProductId+"\"}";
		
		String string = HttpUtils.doPostJSON(url, postJSON);
		
		return parseToJavaObject(string, MealInfo.class);
	}
	
	
	private static <T> T parseToJavaObject(String string, Class<T> clazz) {
		JSONObject json = JSON.parseObject(string);
		return json.toJavaObject(clazz);
	}
	
	public static String getBase64PDFReportByOrderNum(String baseUrl, String accessToken, String orderNum) {

		// String url = String.format("%s%s?accessToken=%s", baseUrl,
		// Apis.pdfReport, accessToken);
		//
		// String postJSON = "{orderNum:\""+orderNum+"\"}";
		//
		// String string = HttpUtils.doPostJSON(url, postJSON);

		// JSONObject json = JSON.parseObject(string);

		// MealListResult result = json.toJavaObject(MealListResult.class);

		return null;
	}

//	private static String accessToken = "AnrvX-WMLX4OwdOmuPuNwHgSh_T_zIxwE_60-7CsaA62oP7F2Swj7rjPgIAyXIpn4sTLzAalp4pWtkB8pNCIXjO6eKpCcNLReLd4T82h926nu7fEk3zoswxR_pMPwGe_k2";
//	private static String baseUrl = "https://test-api.mytijian.com/open-api";
//	private static String signKey = "4cdeb99932614814a96492b662f08aa1";

	// 20170919150410946000146
	// 20170919150734040000365

	public static void main(String[] args) {
		
//		OpenConfig c = new OpenConfig();
//		c.setBaseUrl("http://192.168.2.38:7777/open-api");
//		c.setAccessToken("cHn4C084SpwSQBuq5alnEeeai7msJl3vm_LprVp994a6-awvCLOr4uWdalAumwo-DGnSNI1bmbrtAPZ6m_P_-N8Kk2dkDfrIugnbT0qMol94IIknW4oNBKTd1e5Y7IVG16");
//		MealInfo info = getMealByTmallProductId(c, "554919906396");

		//		BaseResult result = revoke(baseUrl, accessToken, signKey, "20170919150410946000146");
//		System.out.println(result.getMsg());

		// MealListResult result = getMeals(baseUrl, accessToken, 11892);
		//
		// RegisterParam regparam = new RegisterParam();
		// regparam.setUsername("林知昊12");
		// regparam.setIdcard("331082198608200333");
		// regparam.setMobile("17777777777");
		//
		// RegisterResult userResult =
		// register("https://test-api.mytijian.com/open-api", accessToken,
		// signKey, regparam);
		//
		// regparam.setOpenId(userResult.getOpenId());
		//
		// userResult = updateUserInfo("https://test-api.mytijian.com/open-api",
		// accessToken, signKey, regparam);
		//
		// CounterResult count = getCounter(baseUrl, accessToken, 5,
		// "2017-09-20", "2017-09-28");
		//
		// BookParam bookParam = new BookParam();
		// bookParam.setExamAccountName(MD5.stringMD5("林知昊12" + signKey));
		// bookParam.setIdCard(MD5.stringMD5("331082198608200333" + signKey));
		// bookParam.setMobile(MD5.stringMD5("17777777777" + signKey));
		//
		// bookParam.setOrderPrice(result.getMeals().get(0).getPrice());
		// bookParam.setExamTimeIntervalId(count.getDayCapacitys().get(2).getPeriodCapacitys().get(0).getPeriod());
		// bookParam.setMealId(11892);
		// bookParam.setOpenId(userResult.getOpenId());
		// bookParam.setExamDate(count.getDayCapacitys().get(6).getDateStr());
		//
		// BookResult bookresult = book(baseUrl, accessToken, signKey,
		// bookParam);
		//
		// System.out.println(bookresult.getOrderNum());
		// OrderListResult result =
		// getOrderStatus("https://test-api.mytijian.com/open-api", accessToken,
		// "20160815105817991018489");

		// getOrderStatus("", accessToken, "2131241314");
		// CounterResult result = getCounter("http://127.0.0.1:7777/open-api",
		// accessToken, 5, "2017-09-20", "2017-09-28");

		// System.out.println(result.getDayCapacitys().size());

		// MealListResult result =
		// getMeals("https://test-api.mytijian.com/open-api", accessToken,
		// 11574);
		// System.out.println(result.getMeals().get(0).getExamItems().size());

		// System.out.println(nonce("https://test-api.mytijian.com/open-api",
		// "0xWZddBRs3s6gpYbYFMatgAHOjxWW-oIBlNsVyfaEBsLeFZSr1Q2U2BnF-QiaWeuK7OsTUpogBuvjSC_nfjiMJMw7SuWX9p7HN2ScZ0NyqF8TQqaUFBL-OFJdw8XzEr6rMJUIgU_zDtBIo0Gn9N3Ok1kRiCDDCRxeeuIlp"));

		// RegisterParam p = new RegisterParam();
		// p.setUsername("林知昊12");
		// p.setIdcard("331082198608200333");
		// p.setMobile("17777777777");
		//
		// RegisterResult result =
		// register("https://test-api.mytijian.com/open-api",
		// "0xWZddBRs3s6gpYbYFMatgAHOjxWW-oIBlNsVyfaEBsLeFZSr1Q2U2BnF-QiaWeuK7OsTUpogBuvjSC_nfjiMJMw7SuWX9p7HN2ScZ0NyqF8TQqaUFBL-OFJdw8XzEr6rMJUIgU_zDtBIo0Gn9N3Ok1kRiCDDCRxeeuIlp",
		// "4cdeb99932614814a96492b662f08aa1", p);
		//
		// System.out.println(result.getOpenId());

	}

	@Override
	public boolean isLive(AppConfig config) {
		String url = String.format("%s%s?accessToken=%s", config.getBaseUrl(), Apis.nonpNosign, config.getAppAccessToken());
		String string = HttpUtils.doGet(url);
		JSONObject json = JSON.parseObject(string);
		String result = json.getString("result");
		return "success".equals(result);
	}

	@Override
	public BaseResult changeExamDate(AppConfig config, ChangeExamDateParam param) {
		String nonce = nonce(config);
		String postJSON = JSON.toJSONString(param);

		String sign = MD5.stringMD5(String.format("%s%s%s", nonce, postJSON, config.getAppSignKey()));

		String postUrl = String.format("%s%s?accessToken=%s&nonce=%s&sign=%s", config.getBaseUrl(), Apis.changeExamDate,
				config.getAppAccessToken(), nonce, sign);
		
		String jsonResult  = HttpUtils.doPostJSON(postUrl, postJSON);
		
		return parseToJavaObject(jsonResult, BaseResult.class);
	}

	@Override
	public UserInfo userInfo(AppConfig config, String openId) {
		String postJSON = "{\"openId\":\"" + openId + "\"}";
		String sign = MD5.stringMD5(String.format("%s%s", postJSON, config.getAppSignKey()));

		String postUrl = String.format("%s%s?accessToken=%s&sign=%s", config.getBaseUrl(), 
				Apis.userInfo, config.getAppAccessToken(), sign);

		String string = HttpUtils.doPostJSON(postUrl, postJSON);
		
		return parseToJavaObject(string, UserInfo.class);
	}
}
